using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

using SlimDX.Direct3D9;

namespace miciv.Rendering
{
    public class RendererManager : HashtableManager<string, IRenderer>
    {
        protected CoreContext m_coreContext;
        protected Device m_d3dDevice;
        protected List<IRendererContext> m_lstRendererContextes;

        public RendererManager(CoreContext _coreContext)
        {
            this.m_coreContext = _coreContext;
            this.m_d3dDevice = this.m_coreContext.GetData<Device>("D3DDevice");
            this.m_lstRendererContextes = new List<IRendererContext>();
        }

        public bool AddRendererContext(IRendererContext _rendererContext)
        {
            if (false == this.m_lstRendererContextes.Contains(_rendererContext))
            {
                this.m_lstRendererContextes.Add(_rendererContext);
                return true;
            }
            return false;
        }

        public void RemoveRendererContext(IRendererContext _rendererContext)
        {
            if (false != this.m_lstRendererContextes.Contains(_rendererContext))
            {
                this.m_lstRendererContextes.Remove(_rendererContext);
            }
        }

        public IRenderer GetByVertexDefinition(string _strVertexDefinition, IRenderable _renderable)
        {
            VertexDefinition vertexFormat = this.m_coreContext.GetData<VertexDefinitionManager>("VertexDefinitionManager").Get(_strVertexDefinition);
            if (null != vertexFormat)
            {
                foreach (DictionaryEntry de in this.m_htblData)
                {
                    IRenderer renderer = de.Value as IRenderer;
                    if ((false != renderer.CanSupportVertexDefinition(vertexFormat)) && (false != renderer.CanSupportRenderable(_renderable)))
                    {
                        return renderer;
                    }
                }
            }
            return null;
        }

        public IRenderer GetByVertexDefinition(string _strVertexDefinition, Type _type)
        {
            VertexDefinition vertexFormat = this.m_coreContext.GetData<VertexDefinitionManager>("VertexDefinitionManager").Get(_strVertexDefinition);
            if (null != vertexFormat)
            {
                foreach (DictionaryEntry de in this.m_htblData)
                {
                    IRenderer renderer = de.Value as IRenderer;
                    if ((false != renderer.CanSupportVertexDefinition(vertexFormat)) && (false != renderer.CanSupportRenderableType(_type)))
                    {
                        return renderer;
                    }
                }
            }
            return null;
        }

        public void ScreenSizeChanged(int _sWidth, int _sHeight)
        {
            foreach (IRendererContext rendererContext in this.m_lstRendererContextes)
            {
                if (null != rendererContext.ScreenSizeChanged)
                {
                    rendererContext.ScreenSizeChanged(_sWidth, _sHeight);
                }
            }
        }

        public void Render()
        {
            Viewport backupViewport = this.m_d3dDevice.Viewport;

            foreach (IRendererContext rendererContext in this.m_lstRendererContextes)
            {
                if (null != rendererContext.BeginScene)
                {
                    rendererContext.BeginScene(rendererContext);
                }
            }

            foreach (DictionaryEntry de in this.m_htblData)
            {
                (de.Value as IRenderer).BeginScene();
            }

            foreach (IRendererContext rendererContext in this.m_lstRendererContextes)
            {
                if ((false == rendererContext.IsNullViewport) && (this.m_d3dDevice.Viewport != rendererContext.Viewport))
                {
                    this.m_d3dDevice.Viewport = rendererContext.Viewport;
                }

                rendererContext.Clear();

                foreach (DictionaryEntry de in this.m_htblData)
                {
                    IRenderer renderer = de.Value as IRenderer;
                    renderer.RendererContext = rendererContext;
                    renderer.BeginRender();
                    renderer.RenderAllOpaques();
                    renderer.RenderAllTransparents();
                    renderer.EndRender();
                }
            }

            foreach (DictionaryEntry de in this.m_htblData)
            {
                (de.Value as IRenderer).EndScene();
            }

            foreach (IRendererContext rendererContext in this.m_lstRendererContextes)
            {
                if (null != rendererContext.EndScene)
                {
                    rendererContext.EndScene(rendererContext);
                }
            }

            this.m_d3dDevice.Viewport = backupViewport;
        }
    }
}
